﻿using UnityEngine;
using System.Collections.Generic;

/// <summary>
/// Animator 관리 컴포넌트. Animator 컴포넌트가 없으면 에러.
/// </summary>
public class AnimatorHelper : MonoBehaviour
{
    private class PlayContent
    {
        public string name;
        public float fadeTime;

        public PlayContent( string name, float fadeTime )
        {
            this.name = name;
            this.fadeTime = fadeTime;
        }
    }

    private Animator animator;

    private PlayContent current;
    private Queue<PlayContent> reserveQueue = new Queue<PlayContent>();

    public Animator Animator { get { return animator; } }

    public AnimatorStateInfo AnimatorStateInfo { get { return animator.IsInTransition(0) ? animator.GetNextAnimatorStateInfo(0) : animator.GetCurrentAnimatorStateInfo(0); } }

    /// <summary>
    /// 현재 애니메이션 길이.
    /// </summary>
    public float Length { get { return AnimatorStateInfo.length; } }
    /// <summary>
    /// 현재 애니메이션이 재생된 시간 / 현재 애니메이션 길이.
    /// </summary>
    public float NormalizeTime
    {
        get
        {
            float normalizeTime = AnimatorStateInfo.normalizedTime;

            //return normalizeTime - Mathf.Floor(normalizeTime);
            return normalizeTime;
        }
    }
    /// <summary>
    /// 현재 애니메이션이 재생된 시간.
    /// </summary>
    public float CurrentTime { get { return NormalizeTime * Length; } }

    private void Awake()
    {
        animator = GetComponent<Animator>();
    }

    private void Update()
    {
        if(reserveQueue.Count > 0)
        {
            if(current == null)
                CrossFadeFromQueue();
            else
            {
                if(IsPlaying(current.name) && CurrentTime >= Length - reserveQueue.Peek().fadeTime)
                    CrossFadeFromQueue();
            }
        }
    }

    public bool IsPlaying( string name )
    {
        return AnimatorStateInfo.IsName(name);
    }

    public bool IsPlayingTag( string tag )
    {
        return AnimatorStateInfo.IsTag(tag);
    }

    private void ClearCrossFadeQueue()
    {
        reserveQueue.Clear();
    }

    /// <summary>
    /// 애니메이션이 끝난 후 자동 재생.
    /// </summary>
    /// <param name="name"></param>
    /// <param name="fadeTime"></param>
    public void CrossFadeEnqueue( string name, float fadeTime = 0f )
    {
        reserveQueue.Enqueue(new PlayContent(name, fadeTime));
    }

    private void CrossFadeFromQueue()
    {
        PlayContent c = reserveQueue.Dequeue();

        try
        {
            Animator.CrossFade(c.name, c.fadeTime, -1, 0);
        }
        catch(System.Exception e)
        {
            Debug.LogWarning("CrossFadeFromQueue : " + e.Message);
        }

        current = c;
    }

    /// <summary>
    /// 애니메이션 큐를 비우고 강제 재생.
    /// </summary>
    /// <param name="name"></param>
    /// <param name="fadeTime"></param>
    public void CrossFade( string name, float fadeTime = 0f )
    {
        ClearCrossFadeQueue();

        CrossFadeEnqueue(name, fadeTime);

        CrossFadeFromQueue();
    }

    public static AnimatorHelper Get( Transform target )
    {
        AnimatorHelper component = target.GetComponent<AnimatorHelper>();

        if(component == null)
            component = target.gameObject.AddComponent<AnimatorHelper>();

        return component;
    }

    public static AnimatorHelper Get( GameObject target )
    {
        AnimatorHelper component = target.GetComponent<AnimatorHelper>();

        if(component == null)
            component = target.AddComponent<AnimatorHelper>();

        return component;
    }
}